home *** CD-ROM | disk | FTP | other *** search
/ Aminet 52 / Aminet 52 (2002)(GTI - Schatztruhe)[!][Dec 2002].iso / Aminet / dev / gg / ncurses-5.3.lha / ncurses-5.3 / test / gdc.c < prev    next >
C/C++ Source or Header  |  2002-10-24  |  7KB  |  317 lines

  1. /*
  2.  * Grand digital clock for curses compatible terminals
  3.  * Usage: gdc [-s] [n]   -- run for n seconds (default infinity)
  4.  * Flags: -s: scroll
  5.  *
  6.  * modified 10-18-89 for curses (jrl)
  7.  * 10-18-89 added signal handling
  8.  *
  9.  * $Id: gdc.c,v 1.23 2002/08/10 19:20:14 tom Exp $
  10.  */
  11.  
  12. #include <time.h>
  13.  
  14. #include <test.priv.h>
  15.  
  16. #define YBASE    10
  17. #define XBASE    10
  18. #define XLENGTH    54
  19. #define YDEPTH    5
  20.  
  21. static short disp[11] =
  22. {
  23.     075557, 011111, 071747, 071717, 055711,
  24.     074717, 074757, 071111, 075757, 075717, 002020
  25. };
  26. static long older[6], next[6], newer[6], mask;
  27.  
  28. static int sigtermed = 0;
  29. static bool redirected = FALSE;
  30. static bool hascolor = FALSE;
  31.  
  32. static RETSIGTYPE
  33. sighndl(int signo)
  34. {
  35.     signal(signo, sighndl);
  36.     sigtermed = signo;
  37.     if (redirected) {
  38.     endwin();
  39.     ExitProgram(EXIT_FAILURE);
  40.     }
  41. }
  42.  
  43. static void
  44. drawbox(void)
  45. {
  46.     chtype bottom[XLENGTH + 1];
  47.     int n;
  48.  
  49.     if (hascolor)
  50.     attrset(COLOR_PAIR(3));
  51.  
  52.     mvaddch(YBASE - 1, XBASE - 1, ACS_ULCORNER);
  53.     hline(ACS_HLINE, XLENGTH);
  54.     mvaddch(YBASE - 1, XBASE + XLENGTH, ACS_URCORNER);
  55.  
  56.     mvaddch(YBASE + YDEPTH, XBASE - 1, ACS_LLCORNER);
  57.     mvinchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
  58.     for (n = 0; n < XLENGTH; n++)
  59.     bottom[n] = ACS_HLINE | (bottom[n] & (A_ATTRIBUTES | A_COLOR));
  60.     mvaddchnstr(YBASE + YDEPTH, XBASE, bottom, XLENGTH);
  61.     mvaddch(YBASE + YDEPTH, XBASE + XLENGTH, ACS_LRCORNER);
  62.  
  63.     move(YBASE, XBASE - 1);
  64.     vline(ACS_VLINE, YDEPTH);
  65.  
  66.     move(YBASE, XBASE + XLENGTH);
  67.     vline(ACS_VLINE, YDEPTH);
  68.  
  69.     if (hascolor)
  70.     attrset(COLOR_PAIR(2));
  71. }
  72.  
  73. static void
  74. standt(int on)
  75. {
  76.     if (on) {
  77.     if (hascolor) {
  78.         attron(COLOR_PAIR(1));
  79.     } else {
  80.         attron(A_STANDOUT);
  81.     }
  82.     } else {
  83.     if (hascolor) {
  84.         attron(COLOR_PAIR(2));
  85.     } else {
  86.         attroff(A_STANDOUT);
  87.     }
  88.     }
  89. }
  90.  
  91. static void
  92. set(int t, int n)
  93. {
  94.     int i, m;
  95.  
  96.     m = 7 << n;
  97.     for (i = 0; i < 5; i++) {
  98.     next[i] |= ((disp[t] >> ((4 - i) * 3)) & 07) << n;
  99.     mask |= (next[i] ^ older[i]) & m;
  100.     }
  101.     if (mask & m)
  102.     mask |= m;
  103. }
  104.  
  105. static void
  106. usage(void)
  107. {
  108.     static const char *msg[] =
  109.     {
  110.     "Usage: gdc [options] [count]"
  111.     ,""
  112.     ,"Options:"
  113.     ,"  -n  redirect input to /dev/null"
  114.     ,"  -s  scroll each number into place, rather than flipping"
  115.     ,""
  116.     ,"If you specify a count, gdc runs for that number of seconds"
  117.     };
  118.     unsigned j;
  119.     for (j = 0; j < SIZEOF(msg); j++)
  120.     fprintf(stderr, "%s\n", msg[j]);
  121.     ExitProgram(EXIT_FAILURE);
  122. }
  123.  
  124. int
  125. main(int argc, char *argv[])
  126. {
  127.     time_t now;
  128.     struct tm *tm;
  129.     long t, a;
  130.     int i, j, s, k;
  131.     int count = 0;
  132.     FILE *ofp = stdout;
  133.     FILE *ifp = stdin;
  134.     bool scrol = FALSE;
  135.  
  136.     setlocale(LC_ALL, "");
  137.  
  138.     signal(SIGINT, sighndl);
  139.     signal(SIGTERM, sighndl);
  140.  
  141.     while ((k = getopt(argc, argv, "sn")) != EOF) {
  142.     switch (k) {
  143.     case 's':
  144.         scrol = TRUE;
  145.         break;
  146.     case 'n':
  147.         ifp = fopen("/dev/null", "r");
  148.         redirected = TRUE;
  149.         break;
  150.     default:
  151.         usage();
  152.     }
  153.     }
  154.     if (optind < argc) {
  155.     count = atoi(argv[optind++]);
  156.     }
  157.     if (optind < argc)
  158.     usage();
  159.  
  160.     if (redirected) {
  161.     char *name = getenv("TERM");
  162.     if (name == 0
  163.         || newterm(name, ofp, ifp) == 0) {
  164.         fprintf(stderr, "cannot open terminal\n");
  165.         ExitProgram(EXIT_FAILURE);
  166.     }
  167.  
  168.     } else {
  169.     initscr();
  170.     }
  171.     cbreak();
  172.     noecho();
  173.     nodelay(stdscr, 1);
  174.     curs_set(0);
  175.  
  176.     hascolor = has_colors();
  177.  
  178.     if (hascolor) {
  179.     int bg = COLOR_BLACK;
  180.     start_color();
  181. #if HAVE_USE_DEFAULT_COLORS
  182.     if (use_default_colors() == OK)
  183.         bg = -1;
  184. #endif
  185.     init_pair(1, COLOR_BLACK, COLOR_RED);
  186.     init_pair(2, COLOR_RED, bg);
  187.     init_pair(3, COLOR_WHITE, bg);
  188.     attrset(COLOR_PAIR(2));
  189.     }
  190.  
  191.   restart:
  192.     for (j = 0; j < 5; j++)
  193.     older[j] = newer[j] = next[j] = 0;
  194.  
  195.     clear();
  196.     drawbox();
  197.  
  198.     do {
  199.     char buf[30];
  200.  
  201.     time(&now);
  202.     tm = localtime(&now);
  203.  
  204.     mask = 0;
  205.     set(tm->tm_sec % 10, 0);
  206.     set(tm->tm_sec / 10, 4);
  207.     set(tm->tm_min % 10, 10);
  208.     set(tm->tm_min / 10, 14);
  209.     set(tm->tm_hour % 10, 20);
  210.     set(tm->tm_hour / 10, 24);
  211.     set(10, 7);
  212.     set(10, 17);
  213.  
  214.     for (k = 0; k < 6; k++) {
  215.         if (scrol) {
  216.         for (i = 0; i < 5; i++)
  217.             newer[i] = (newer[i] & ~mask) | (newer[i + 1] & mask);
  218.         newer[5] = (newer[5] & ~mask) | (next[k] & mask);
  219.         } else
  220.         newer[k] = (newer[k] & ~mask) | (next[k] & mask);
  221.         next[k] = 0;
  222.         for (s = 1; s >= 0; s--) {
  223.         standt(s);
  224.         for (i = 0; i < 6; i++) {
  225.             if ((a = (newer[i] ^ older[i]) & (s ? newer : older)[i])
  226.             != 0) {
  227.             for (j = 0, t = 1 << 26; t; t >>= 1, j++) {
  228.                 if (a & t) {
  229.                 if (!(a & (t << 1))) {
  230.                     move(YBASE + i, XBASE + 2 * j);
  231.                 }
  232.                 addstr("  ");
  233.                 }
  234.             }
  235.             }
  236.             if (!s) {
  237.             older[i] = newer[i];
  238.             }
  239.         }
  240.         if (!s) {
  241.             if (scrol)
  242.             drawbox();
  243.             refresh();
  244.             /*
  245.              * If we're scrolling, space out the refreshes to fake
  246.              * movement.  That's 7 frames, or 6 intervals, which would
  247.              * be 166 msec if we spread it out over a second.  It looks
  248.              * better (but will well on a slow terminal, e.g., less
  249.              * than 9600bd) to squeeze that into a half-second, and use
  250.              * half of 170 msec to ensure that the program doesn't eat
  251.              * a lot of time when asking what time it is, at the top of
  252.              * this loop -TD
  253.              */
  254.             if (scrol)
  255.             napms(85);
  256.         }
  257.         }
  258.     }
  259.  
  260.     /* this depends on the detailed format of ctime(3) */
  261.     (void) strcpy(buf, ctime(&now));
  262.     (void) strcpy(buf + 10, buf + 19);
  263.     mvaddstr(16, 30, buf);
  264.  
  265.     move(6, 0);
  266.     drawbox();
  267.     refresh();
  268.  
  269.     /*
  270.      * If we're not scrolling, wait 1000 msec (1 sec).  Use napms() rather
  271.      * than sleep() because the latter does odd things on some systems,
  272.      * e.g., suspending output as well.
  273.      */
  274.     if (scrol)
  275.         napms(500);
  276.     else
  277.         napms(1000);
  278.  
  279.     /*
  280.      * This is a safe way to check if we're interrupted - making the signal
  281.      * handler set a flag that we can check.  Since we're running
  282.      * nodelay(), the wgetch() call returns immediately, and in particular
  283.      * will return an error if interrupted.  This works only if we can
  284.      * read from the input, of course.
  285.      */
  286.     switch (wgetch(stdscr)) {
  287.     case 'q':
  288.         count = 1;
  289.         break;
  290.     case 's':
  291.         nodelay(stdscr, FALSE);
  292.         break;
  293.     case ' ':
  294.         nodelay(stdscr, TRUE);
  295.         break;
  296. #ifdef KEY_RESIZE
  297.     case KEY_RESIZE:
  298. #endif
  299.     case '?':
  300.         goto restart;
  301.     case ERR:
  302.         if (sigtermed) {
  303.         standend();
  304.         endwin();
  305.         fprintf(stderr, "gdc terminated by signal %d\n", sigtermed);
  306.         ExitProgram(EXIT_FAILURE);
  307.         }
  308.         /* FALLTHRU */
  309.     default:
  310.         continue;
  311.     }
  312.     } while (--count);
  313.     standend();
  314.     endwin();
  315.     ExitProgram(EXIT_SUCCESS);
  316. }
  317.